/******************************************************************************
 *      Mestrado em Ciência da Computação - UFMS
 *		Redes de Computadores - Prof. Dr. Ronaldo Alves Ferreira
 *		Alunos: Geraldo Landre, Marcel Tolentino, Vinícius Bueno
 *****************************************************************************/
 
#ifndef CACHE_H
#define CACHE_H

#define MEGA_BYTE       1048576  // bytes
#define K_BYTE          1024     // bytes
#define SIZE_CHUNK      16 * K_BYTE
#define INIT_SIZE_L1       1     // tamanho arbitrário para quantidade de arquivos na cache
#define INIT_SIZE_L2       1     // tamanho arbitrário para quantidade de arquivos na cache
#define CACHE_FILE      "init_cache.txt"



#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <sys/types.h>
#include <dirent.h>


#include "request.h"
#include "dirmanip.h"

pthread_rwlock_t cache_semaphore;
pthread_rwlockattr_t cache_attr;

typedef struct
{
    int size; // tamanho do arquivo
    int access; // quantidade de acessos
    vstring *request; // requisição que trouxe o arquivo ao servidor
    vstring *file_name; // nome gerado para o arquivo
    struct tm *last_access; // data do último acesso
    struct tm *came_from_server; // data do último recebimento do arquivo vindo do servidor original
}meta_data;

typedef struct
{
    int length;
    int last;
    meta_data **elements;
}heap_level2;

typedef struct
{
    meta_data *data;
    vstring *file_data;
}level1;

typedef struct
{
    int length;
    int last;
    level1 **elements;
}heap_level1;

typedef struct
{
    unsigned int size_l1;
    unsigned int occuped_l1;
    heap_level1 cache_data_l1;

    unsigned int size_l2;
    unsigned int occuped_l2;
    heap_level2 cache_data_l2;
}cache;

cache memory;


/*******************************************************************************
 *      FUNÇÕES DE MANIPULAÇÃO DA ESTRUTURA HEAP QUE CONTÉM OS ARQUIVOS DA
 *
 *                                  CACHE
 ******************************************************************************/

void create_meta_data(meta_data **new_m);

void init_from_file(meta_data **data,vstring *line);

void create_level1(level1 **new_l);

void print_file(meta_data *f);

int left_son(int index,int last);

int right_son(int index,int last);

int get_father(int index);

int minimum(int a, int b);

int maximum(int a, int b);

/*******************************************************************************
 *                      FUNÇÕES PARA CACHE NÍVEL1
 ******************************************************************************/

void print_level1();

void swap_level1(int a, int b);

void heap_down_level1(int index);

void heap_up_level1(int index);

void heapfy_level1();

void remove_heap_level1(int index);

void resize_level1();

void insert_level1(level1 **file);

/*******************************************************************************
 *                      FUNÇÕES PARA CACHE NÍVEL2
 ******************************************************************************/

void print_level2();

void swap_level2(int a, int b);

void heap_down_level2(int index);

void heap_up_level2(int index);

void heapfy_level2();

void remove_heap_level2(int index);

void resize_level2();

void insert_level2(level1 **file);

void sort_level2();

/*******************************************************************************
 *                          FUNÇÕES DE MANIPULAÇÃO DA CACHE
 ******************************************************************************/

void print_cache();

void new_cache();

void create_name_file(vstring **file);

void path_file_cache(vstring **path,vstring *file);

void line_cache_file(meta_data **data,vstring **line);

void init_cache();

int search_request_level1(vstring *request);

int search_request_level2(vstring *request);

void insert_in_cache(level1 **file);

void close_cache();

int hit_level1(int index,vstring **body);

int hit_level2(int index,vstring **body);

#endif